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(t!("errors.u64_too_large_for_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(t!("errors.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(t!("errors.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).ok_or_else(|| {
338 serde::de::Error::custom(t!("errors.invalid_key_modifiers"))
339 })?;
340 }
341 "kind" => {
342 let value = map.next_value::<String>()?;
343 key_event.kind = KeySettings::string_to_key_event_kind(&value)
344 .map_err(serde::de::Error::custom)?;
345 }
346 "state" => {
347 let value = map.next_value()?;
348 key_event.state = KeyEventState::from_bits(value).ok_or_else(|| {
349 serde::de::Error::custom(t!("errors.invalid_key_event_state"))
350 })?;
351 }
352 _ => {
353 map_kind = MapKind::Unknown;
354 break;
355 }
356 },
357 }
358 }
359 match map_kind {
360 MapKind::Unknown => Err(serde::de::Error::custom(t!(
361 "errors.invalid_table_style_or_key_event"
362 ))),
363 MapKind::Style => self.visit_style(style),
364 MapKind::Key => self.visit_key(key_event),
365 }
366 }
367}
368
369impl<'de> Deserialize<'de> for SettingsValue {
370 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
371 where
372 D: serde::Deserializer<'de>,
373 {
374 deserializer.deserialize_any(SettingsValueVisitor)
375 }
376}
377
378impl IntoLua for SettingsValue {
379 fn into_lua(self, lua: &mlua::Lua) -> mlua::Result<mlua::Value> {
380 match self {
381 SettingsValue::Bool(value) => value.into_lua(lua),
382 SettingsValue::Int(value) => value.into_lua(lua),
383 SettingsValue::Float(value) => value.into_lua(lua),
384 SettingsValue::String(value) => value.into_lua(lua),
385 SettingsValue::Style(value) => Ok(mlua::Value::Table(get_style(lua, &value)?)),
386 SettingsValue::Key(value) => Ok(mlua::Value::Table(key_event_to_lua(lua, &value)?)),
387 }
388 }
389}
390
391impl FromLua for SettingsValue {
392 fn from_lua(value: mlua::Value, _lua: &mlua::Lua) -> mlua::Result<Self> {
393 match value {
394 mlua::Value::Boolean(value) => Ok(SettingsValue::Bool(value)),
395 mlua::Value::Integer(value) => Ok(SettingsValue::Int(value)),
396 mlua::Value::Number(value) => Ok(SettingsValue::Float(value)),
397 mlua::Value::String(value) => Ok(SettingsValue::String(value.to_str()?.to_string())),
398 mlua::Value::Table(value) => {
399 if value.contains_key("fg")?
400 || value.contains_key("bg")?
401 || value.contains_key("underline")?
402 || value.contains_key("add_modifier")?
403 || value.contains_key("sub_modifier")?
404 {
405 let mut style = Style::default();
406 set_style(_lua, &mut style, value)?;
407 Ok(SettingsValue::Style(style))
408 } else if value.contains_key("code")?
409 || value.contains_key("modifiers")?
410 || value.contains_key("kind")?
411 || value.contains_key("state")?
412 {
413 let key_event = lua_to_key_event(_lua, &value)?;
414 Ok(SettingsValue::Key(key_event))
415 } else {
416 Err(mlua::Error::RuntimeError(
417 "Invalid table, expected style or key event".to_string(),
418 ))
419 }
420 }
421 _ => Err(mlua::Error::RuntimeError(
422 "Expected boolean, integer, number, string, style or key event".to_string(),
423 )),
424 }
425 }
426}